Skip to content

feat: Implement textDocument/documentColor #20140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nik-rev
Copy link

@nik-rev nik-rev commented Jul 1, 2025

Hi, I'd like to add textDocument/documentColor method to rust-analyzer, it will allow libraries with a type like Color { r: u8, g: u8, b: u8 } to annotate this type with special attributes #[rust_analyzer::color::rgb].

IDEs can then annotate expressions known at compile time that of type Color
with color swatches, similar to how it works for CSS:

image

I added the feature to Helix from the client side (helix-editor/helix#12308) and think it'd be fun to also add it from the server side.


My current plan is to have an API like this:

#[rust_analyzer::color::rgb]
struct Color {
    #[rust_analyzer::color::rgb::r]
    red: f32,
    #[rust_analyzer::color::rgb::g]
    green: f32,
    #[rust_analyzer::color::rgb::b]
    blue: f32,
}

// the expression `Color { ... }` will have a red square next to it!
const RED: Color = Color {
    red: 255,
    green: 0,
    blue: 0,
};

This is what I want for a MVP:

  1. Visit every expression that is known at compile time (is const)
  2. If the type struct of the expression contains
    an attribute #[rust_analyzer::color::rgb], proceed
  3. If there are 3 f32 fields with attribute #[rust_analyzer::color::rgb::{r,g,b}],
    then we have all the necessary information to construct the type itself

Currently, the problem that I face is that I cannot obtain the Type of an expression. type_of_expr returns None:

for event in file.preorder() {
    let syntax::WalkEvent::Leave(syntax_node) = event else { continue };
    let Some(expr) = syntax::ast::Expr::cast(syntax_node) else { continue };
    dbg!(&expr);

    // `type_of_expr` fails... but why?
    let Some(ty) = sema.type_of_expr(&expr) else { continue };
    dbg!(ty);
}

I'm building rust-analyzer with cargo run --release then in .helix/languages.toml I tell the editor to use the built binary:

[language-server.rust-analyzer]
command = "/home/e/contrib/rust-analyzer/target/release/rust-analyzer"

This works. I get hover information, auto-complete. I get custom logs in Helix's log (:log-open).

The current implementation draws a single hard-coded red square in the file, so I assume the problem isn't with my setup

Closes #13122

nik-rev added 2 commits July 1, 2025 15:26
Here, it always returns a single color and enables the language server
capability
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document Color support
1 participant